package com.txtsqlclient.ui;

import java.io.BufferedReader;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * This class is required to capture user's input. Provides ways to capture user input,
 * securely and with masking. Code copied from:
 * http://forum.java.sun.com/thread.jspa?forumID=9&threadID=490728
 * 
 * @author spadda
 */
public class UserInputCapturer {

    /**
     * Refer to this page for more details:
     * http://forum.java.sun.com/thread.jspa?forumID=9&threadID=490728 <br>
     * Note: might not work on Mac
     * 
     * @param prompt
     * @return the password in the form of a char[]. Reset the char[] after encrypting any
     *         secure details.
     */
    public static final char[] getSecureMaskedLine(String prompt) throws IOException {
        // password holder
        char[] password = new char[0];
        CharArrayWriter caw = getMaskedInput(prompt);
        password = caw.toCharArray();
        // The buffer can be erased char-by-char to avoid breach of any secure data in the
        // memory.
        caw.close();
        return password;
    }

    public static final String getMaskedLine(String prompt) {
        CharArrayWriter caw = getMaskedInput(prompt);
        caw.close();
        return caw.toString();
    }

    /**
     * This method is required to read the user's input while applying masking.
     * 
     * @param prompt
     * @return a Writer object, from which the char array, or the string can be obtained.
     *         Please make sure to close the stream.
     */
    private static CharArrayWriter getMaskedInput(String prompt) {
        CharArrayWriter caw = new CharArrayWriter();
        // password holder
        MaskingThread maskingthread = new MaskingThread(prompt);
        Thread thread = new Thread(maskingthread);
        thread.start();
        try {
            // block until enter is pressed
            while (true) {
                char c = (char) System.in.read();
                // assume enter pressed, stop masking
                maskingthread.stopMasking();
                if (c == '\r') {
                    c = (char) System.in.read();
                    if (c == '\n') {
                        break;
                    } else {
                        continue;
                    }
                } else if (c == '\n') {
                    break;
                } else {
                    // store the password
                    caw.append(c);
                }
            }
        } catch (IOException ie) {
            System.out.println("Error while reading user input");
            ie.printStackTrace();
        }
        return caw;
    }

    public static final String getLine(String prompt) {
        System.out.print(prompt);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = null;
        try {
            line = br.readLine();
        } catch (IOException e) {
            System.out.println("Error while reading user input");
            e.printStackTrace();
        }
        return line;
    }

}
